package org.lex.depends.core.analyzer;

import java.io.File;
import java.io.InputStream;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Queue;

import org.lex.depends.core.asm.VisitClass;
import org.lex.depends.core.resource.IResource;
import org.lex.depends.core.resource.ResourceManager;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.tree.ClassNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FullDependsAnalyzer implements IDependsAnalyzer {
	public static void main(String[] args) {
		IDependsAnalyzer ana = new FullDependsAnalyzer(FullDependsAnalyzer.class.getName());
		System.out.println(ana.analyze());
	}

	private Logger log = LoggerFactory.getLogger(FullDependsAnalyzer.class);

	private String className = null;

	public FullDependsAnalyzer(String className) {
		this.className = className;
	}

	@Override
	public IAnalyzerResult analyze() {
		AnalyzerResult result = new AnalyzerResult();
		Collection<String> visited = result.getDependentClasses();

		Queue<String> queue = new LinkedList<String>();
		queue.offer(className);
		while (false == queue.isEmpty()) {
			String top = queue.poll();
			if (visited.contains(top)) {
				log.debug(top + " has been visited, skip");
				continue;
			}
			if (top.startsWith("java")) {
				log.debug(top + " is system class, skip");
				continue;
			}
			log.debug("---begin visit: " + top + " ---");
			try {
				IResource res = ResourceManager.getInstance().getResource(top);
				if (null == res) {
					log.error("-----" + top + " NOT FOUND!!!!");
					result.getUnresolvedClasses().add(top);
					continue;
				}
				InputStream is = res.getInputStream();
				ClassReader cr = new ClassReader(is);
				ClassNode root = new ClassNode();
				cr.accept(root, ClassReader.SKIP_DEBUG);
				root.accept(new VisitClass(queue));
				visited.add(top);
			} catch (Exception e) {
				log.error("name=" + top, e);
			}
			log.debug("---end visit: " + top + " ---");
		}
		for (String className : visited) {
			File file = ResourceManager.getInstance().getLocation(className);
			result.getDependentFiles().add(file);
		}
		return result;
	}
}
